/*
 * mergeifunctions.c
 *
 *  Created on: 06/09/2011
 *      Author: ramiro
 */

#include "constantes.h"
#include "merger.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

char* extraerCampo2(char *linea) {

	char *posSeparadorCampo = strchr(linea, ' ');
	int cantCarcteresACopiar = abs(linea - posSeparadorCampo);

	char* campo = malloc(cantCarcteresACopiar+1);

	strncpy(campo, linea, cantCarcteresACopiar);

	campo[cantCarcteresACopiar] = '\0';

	return campo;
}

void pasarAMayusculas2(char *palabra) {

	int i, longitudPalabra = strlen(palabra);

	for (i = 0; i < longitudPalabra; i++)
		palabra[i] = (char) toupper((int) (palabra[i]));
	palabra[i] = '\0';
}


char *mergeLines(char * line1, char * line2, char* clave2) {

	unsigned int length = 0;
	length += strlen(line1) + strlen(line2) - strlen(clave2) +1;

	char *lineBuffer = (char *)malloc(sizeof(char) * length);
	if (lineBuffer == NULL)
		return NULL;


	strcpy(lineBuffer,line1);
	strcat(lineBuffer + strlen(line1),line2 + strlen(clave2));

	return lineBuffer;
}

char *readLine(FILE *file) {

    if (file == NULL) {
        printf("Error: file pointer is null.");
        exit(1);
    }

    int maximumLineLength = 64;
    char *lineBuffer = (char *)malloc(sizeof(char) * maximumLineLength);

    if (lineBuffer == NULL) {
        printf("Error allocating memory for line buffer.");
        exit(1);
    }

    char ch = getc(file);
    int count = 0;

    while ((ch != '\n') && (ch != EOF)) {
        if (count == maximumLineLength) {
            maximumLineLength += 64;
            lineBuffer = realloc(lineBuffer, maximumLineLength);
            if (lineBuffer == NULL) {
                printf("Error reallocating space for line buffer.");
                exit(1);
            }
        }
        lineBuffer[count] = ch;
        count++;

        ch = getc(file);
    }

    if (count == 0) {
    	free(lineBuffer);
    	//EOF
    	return NULL;
    }
    lineBuffer[count] = '\0';
    lineBuffer = realloc(lineBuffer, count + 1);
    return lineBuffer;
}

void merge(FILE* pFile1, FILE* pFile2, int caseSensitive) {
	char *linea1 = NULL;
	char *linea2 = NULL;
	//char *restoLinea2 = NULL;

	char *clave1 = NULL, *clave2 = NULL;

	int salir = FALSE;
	char *lineaAGrabar = NULL;

	fpos_t posArchivo2;

	while (linea2 == NULL || clave2 == NULL || (linea2 != NULL &&strcmp(linea2, "") == 0) || (clave2 != NULL && strcmp(clave2, "") == 0)) {
		fgetpos(pFile1,&posArchivo2);

		//if (fgets(linea2, LARGO_BUFFER_ARCHIVOS, pFile2)) {
		linea2 = readLine(pFile2);
		if (linea2 != NULL) {
			clave2 = extraerCampo2(linea2);
			if (caseSensitive)
				pasarAMayusculas2(clave2);
		}
	}

	if (strcmp(linea2, "") == 0 || strcmp(clave2, "") == 0) {
		exit(0);
	}

	while (!salir) {
		//if (fgets(linea1, LARGO_BUFFER_ARCHIVOS, pFile1)) {
		if (linea1 != NULL) {
			free(linea1);
			linea1 = NULL;
		}
		if (clave1 != NULL) {
			free(clave1);
			clave1 = NULL;
		}

		linea1 = readLine(pFile1);
		if (linea1 != NULL) {
			clave1 = extraerCampo2(linea1);
			if (caseSensitive)
				pasarAMayusculas2(clave1);
		}

		if (!feof(pFile1) && linea1 != NULL && clave1 != NULL && strcmp(clave1, "") != 0) {

			unsigned char key2Found = 0;
			unsigned char validPos = 0;
			fpos_t tempPosArchivo2;

			while (clave2 != NULL &&  strcmp(clave1, clave2) != 0 && !feof(pFile2)) {
				// avanzo en el archivo 2
				fgetpos(pFile2,&tempPosArchivo2);
				validPos = 1;

				if (linea2 != NULL) {free(linea2); linea2 = NULL;}
				if (clave2 != NULL) {free(clave2); clave2 = NULL;}

				linea2 = readLine(pFile2);
				if (linea2 != NULL) {
					clave2 = extraerCampo2(linea2);
					if (caseSensitive)
						pasarAMayusculas2(clave2);
				}

			}

			if (clave2 != NULL && strcmp(clave1, clave2) == 0) {
				key2Found = 1;
				if (validPos == 1) {
					posArchivo2 = tempPosArchivo2;
				}

				lineaAGrabar = mergeLines(linea1,linea2,clave2);
				if (lineaAGrabar != NULL) {
					puts(lineaAGrabar);
					//putchar('\n');
					free(lineaAGrabar);
					lineaAGrabar = NULL;
				}
				else {
	                printf("Error reallocating space for line buffer.");
	                exit(1);
				}
			}

			if (key2Found == 0) {
				fsetpos(pFile2,&posArchivo2);

				if(linea2 != NULL) {free(linea2); linea2 = NULL;}
				if (clave2 != NULL) {free(clave2); clave2 = NULL;}

				linea2 = readLine(pFile2);
				if (linea2 != NULL) {
					clave2 = extraerCampo2(linea2);
					if (caseSensitive)
						pasarAMayusculas2(clave2);
				}
			}
		} else {
			salir = TRUE;
		}
	}

	if (linea1 != NULL) {
		free(linea1);
		linea1 = NULL;
	}

	if (linea2 != NULL) {
		free(linea2);
		linea2 = NULL;
	}

	if (clave2 != NULL) {
		free(clave2);
		clave2 = NULL;
	}

	if (clave1 != NULL) {
		free(clave1);
		clave1 = NULL;
	}

	if (lineaAGrabar != NULL) {
		free(lineaAGrabar);
		lineaAGrabar = NULL;
	}
}
